/*
 * Copyright (c) 2009. Silenus Consultoria, S.L.
 */

// reference local blank image
Ext.BLANK_IMAGE_URL = CONTEXT_PATH + '/ext/resources/images/default/s.gif';
Ext.SSL_SECURE_URL = CONTEXT_PATH + '/blank.html';

// Encoding for ajax form POST
/** @namespace Ext.lib */
Ext.lib.Ajax.defaultPostHeader += '; charset=UTF-8';

// The timeout
Ext.Ajax.timeout = 120000;


Ext.namespace("Survey");



/**
 * Survey dialog.
 *
 * @param config the configuration.
 */
Survey.SurveyPanel = function(config) {
	Survey.SurveyPanel.superclass.constructor.call(this, config);
};


Ext.extend(Survey.SurveyPanel, Ext.FormPanel, {

	surveyData: null,

	provinceCombo: null,

	councilCombo: null,

	trainingCombo: null,

	internetCombo: null,

	areas: null,

	AreaRecord: null,

	PathRecord: null,

	QuestionRecord: null,

	AnswerRecord: null,

	areasStore: null,

	pathsStore: null,

	questionsStore: null,

	areasCombo: null,

	pathsCombo: null,

	questionsCombo: null,

	trainingPreference: null,

	answersStore: null,

	answersGrid: null,

	entityField: null,

	entityValid: false,

	initComponent: function() {

		// First we must construct dynamic areas and path panels

		this.areas = [];

		var currentQuestion = null, prevQuestion = null;
		var area = null, path = null;

		for(var i = 0; i < this.surveyData.questions.length; ++i) {
			prevQuestion = currentQuestion;
			currentQuestion = this.surveyData.questions[i];

			// Detected area switch
			if((prevQuestion == null) || (prevQuestion.id_area != currentQuestion.id_area)) {
				// Push old area panel
				if(area != null) {
					this.areas.push(area);
				}
				// Init new area panel
				area = {
					id: currentQuestion.id_area,
					code: currentQuestion.area_code,
					description: currentQuestion.area_description,
					paths: []
				};
			}

			// Detected path switch
			if((prevQuestion == null) || (prevQuestion.id_path != currentQuestion.id_path)) {
				// Push old path panel
				if(path != null) {
					area.paths.push(path);
				}
				// Init new path panel
				path = {
					id:  currentQuestion.id_path,
					code: currentQuestion.path_code,
					description: currentQuestion.path_description,
					questions: []
				};
			}

			path.questions.push({
				id: currentQuestion.id_question,
				code: currentQuestion.question_code,
				description: currentQuestion.question_description
			});

		}

		// End
		if(area != null) {
			if(path != null) {
				area.paths.push(path);
			}
			this.areas.push(area);
		}


		// Build records
		this.AreaRecord = Ext.data.Record.create([
			{name: 'id'},
			{name: 'code'},
			{name: 'description'},
			{name: 'paths'}
		]);

		this.PathRecord = Ext.data.Record.create([
			{name: 'id'},
			{name: 'code'},
			{name: 'description'},
			{name: 'questions'}
		]);

		this.QuestionRecord = Ext.data.Record.create([
			{name: 'id'},
			{name: 'code'},
			{name: 'description'}
		]);

		this.AnswerRecord = Ext.data.Record.create([
			{name: 'id'},
			{name: 'area_id'},
			{name: 'area_description'},
			{name: 'path_id'},
			{name: 'path_description'},
			{name: 'question_id'},
			{name: 'question_description'},
			{name: 'preference_id'},
			{name: 'preference_description'}
		]);


		// Load areas
		this.areasStore =  new Ext.data.Store({
			proxy: new Ext.data.MemoryProxy(this.areas),
			reader: new Ext.data.JsonReader({id: 'id'}, this.AreaRecord),
			fields: ['id', 'code', 'description', 'paths']
		});

		this.areasStore.load({params: {}, callback: Ext.emptyFn, add: false});

		// Build combos
		this.areasCombo = new Ext.form.ComboBox({
			fieldLabel: MSG['area'],
			hiddenName: 'area',
			width: 150,
			mode: 'remote',
			store: this.areasStore,
			emptyText: MSG['area.empty'],
			tpl: new Ext.XTemplate(
					'<tpl for="."><div class="search-item">',
					'<h3>{description}</h3>',
					'{code} - {description}',
					'</div></tpl>'
					),
			itemSelector: 'div.search-item',
			minChars: 0,
			typeAhead: false,
			valueField: 'id',
			displayField: 'description',
			triggerAction: 'all',
			listeners: {
				blur: function () {
					if (this.getRawValue() == "") {
						this.clearValue();
					}
				}
			}
		});

		this.areasCombo.on("select", this.onSelectedArea, this);

		this.pathsStore = new Ext.data.Store({
			proxy: new Ext.data.MemoryProxy([]),
			reader: new Ext.data.JsonReader({id: 'id'}, this.PathRecord),
			fields: ['id', 'code', 'description', 'questions']
		});

		this.pathsCombo = new Ext.form.ComboBox({
			fieldLabel: MSG['path'],
			hiddenName: 'path',
			width: 400,
			mode: 'remote',
			store: this.pathsStore,
			emptyText: MSG['path.empty'],
			tpl: new Ext.XTemplate(
					'<tpl for="."><div class="search-item">',
					'<h3>{description}</h3>',
					'{code} - {description}',
					'</div></tpl>'
					),
			itemSelector: 'div.search-item',
			minChars: 2,
			typeAhead: false,
			valueField: 'id',
			displayField: 'description',
			triggerAction: 'all',
			listeners: {
				blur: function () {
					if (this.getRawValue() == "") {
						this.clearValue();
					}
				}
			}
		});

		this.pathsCombo.on("select", this.onSelectedPath, this);

		this.questionsStore = new Ext.data.Store({
			proxy: new Ext.data.MemoryProxy([]),
			reader: new Ext.data.JsonReader({id: 'id'}, this.QuestionRecord),
			fields: ['id', 'code', 'description']
		});

		this.questionsCombo = new Ext.form.ComboBox({
			fieldLabel: MSG['question'],
			hiddenName: 'question',
			width: 500,
			mode: 'remote',
			store: this.questionsStore,
			emptyText: MSG['question.empty'],
			tpl: new Ext.XTemplate(
					'<tpl for="."><div class="search-item">',
					'<h3>{description}</h3>',
					'{code} - {description}',
					'</div></tpl>'
					),
			itemSelector: 'div.search-item',
			minChars: 2,
			typeAhead: false,
			valueField: 'id',
			displayField: 'description',
			triggerAction: 'all',
			listeners: {
				blur: function () {
					if (this.getRawValue() == "") {
						this.clearValue();
					}
				}
			}
		});

		this.questionsCombo.on("select", this.onSelectedQuestion, this);

		this.trainingPreference = new Common.SimpleCombo({
			hiddenName: 'preference',
			fieldLabel: MSG['training.preference'],
			emptyText: MSG['preference.empty'],
			data: Common.TrainingPreferences,
			width: 100,
			value: 1
		});

		// Prepare province combo
		this.provinceCombo = new Common.LinkableCombo({
			fieldLabel: MSG['council.province'],
			hiddenName: 'province',
			width: 160,
			mode: 'local',
			store: new Ext.data.SimpleStore({
				fields: ['id', 'name'],
				data: Common.Provinces
			}),
			valueField: 'id',
			displayField: 'name',
			triggerAction: 'all',
			linkParam: 'id',
			allowBlank: false,
			tabIndex: 5
		});

		// Prepare council combo
		this.councilCombo = new Common.LinkableCombo({
			fieldLabel: MSG['council'],
			hiddenName: 'council',
			width: 200,
			mode: 'remote',

			store: new Ext.data.JsonStore({
				url: CONTEXT_PATH + '/councils.json',
				root: 'items',
				fields: ['id', 'name']
			}),

			valueField: 'id',
			displayField:'name',
			triggerAction: 'all',
			allowBlank: false,
			tabIndex: 6
		});

		// Link combos
		this.provinceCombo.addLinkedField(this.councilCombo);


		// Training combo
		this.trainingCombo = new Ext.form.ComboBox({
			fieldLabel: MSG['training'],
			hiddenName: 'training',
			width: 250,
			mode: 'remote',
			store: new Ext.data.JsonStore({
				url: CONTEXT_PATH + '/trainings.json',
				root: 'results',
				fields: ['id', 'code', 'name', 'description'],
				baseParams: { organization: this.surveyData.organization.id }
			}),
			tpl: new Ext.XTemplate(
					'<tpl for="."><div class="search-item">',
					'<h3>{name}</h3>',
					'{code} - {description}',
					'</div></tpl>'
					),
			itemSelector: 'div.search-item',
			minChars: 2,
			typeAhead: false,
			valueField: 'id',
			displayField: 'name',
			triggerAction: 'all',

			listeners: {
				blur: function () {
					if (this.getRawValue() == "") {
						this.clearValue();
					}
				}
			}
		});

		// Internet
		this.internetCombo = new Common.SimpleCombo({
			hiddenName: 'internetConnection',
			fieldLabel: MSG['internet'],
			data: Common.InternetConnection,
			width: 60,
			allowBlank: false
		});

		// Answers grid

		this.answersStore = new Ext.data.Store({
			proxy: new Ext.data.MemoryProxy([]),
			reader: new Ext.data.JsonReader({id: 'id'}, this.AnswerRecord),
			fields: ['id', 'area_description', 'path_description', 'question_description', 'preference_description']
		});

		this.answersGrid = new Ext.grid.GridPanel({
			title: 'Respuestas',
			height: 350,
			autoScroll: true,
			viewConfig: {
				emptyText: MSG['survey.questions.empty'],
				forceFit: true
			},
			cm: new Ext.grid.ColumnModel([
				{header: MSG['area'], dataIndex: 'area_description', width: 40, sortable: true},
				{header: MSG['path'], dataIndex: 'path_description', width: 120, sortable: true},
				{header: MSG['question'], dataIndex: 'question_description', width: 400, sortable: true},
				{header: MSG['training.preference'], dataIndex: 'preference_description', width: 50, sortable: true}
			]),
			store: this.answersStore
		});


		this.iconCls = 'detecta-logo';

		this.entityField = new Ext.form.TextField({
			fieldLabel: MSG['DNI'],
			name: 'DNI',
			anchor: '95%',
			allowBlank:false,
			vtype: 'DNI',
			minLength: 9,
			maxLength: 9,
			tabIndex: 3
		});

		this.entityField.on("change", this.onEntityChanged, this);

		this.items = [{
			xtype: 'hidden',
			name: 'survey',
			value: this.surveyData.id
		}, {
			xtype: 'fieldset',
			title: MSG['personal.data'],
			collapsible: true,
			height: 160,
			items:[{
				layout: 'column',
				border: false,
				height: 200,
				items: [{
					layout: 'form',
					columnWidth: .5,
					border: false,
					labelWidth: 70,
					items: [{
						xtype: 'textfield',
						fieldLabel: MSG['firstname'],
						name: 'firstName',
						allowBlank:false,
						anchor: '95%',
						tabIndex: 1
					}, this.entityField,
						this.provinceCombo,
						this.trainingCombo]
				}, {
					layout: 'form',
					columnWidth: .5,
					border: false,
					labelWidth: 120,
					items:[{
						xtype: 'textfield',
						fieldLabel: MSG['lastname'],
						name: 'lastName',
						allowBlank:false,
						anchor: '95%',
						tabIndex: 2
					}, {
						xtype: 'textfield',
						fieldLabel: MSG['email'],
						name: 'email',
						vtype: 'email',
						allowBlank:false,
						anchor: '95%',
						tabIndex: 4
					},
						this.councilCombo,
						this.internetCombo]
				}]
			}]
		}, {
			xtype: 'fieldset',
			title: MSG['survey.questions'],
			collapsible: true,
			height: 180,
			buttonAlign: 'center',
			items: [
				this.areasCombo,
				this.pathsCombo,
				this.questionsCombo,
				this.trainingPreference
			],
			buttons: [{
				text: MSG['button.add'],
				handler: this.addQuestion,
				scope: this
			}, {
				text: MSG['button.remove'],
				handler: this.removeQuestion,
				scope: this
			}]
		}, this.answersGrid];


		// Buttons
		this.buttons = [{
			text: MSG['button.save'],
			handler: this.onSave,
			scope: this
		}, {
			text: MSG['button.cancel'],
			handler: this.onCancel,
			scope: this
		}];

		this.tools = [{
			id: 'help',
			handler:  this.onHelp,
			qtip: MSG['help'],
			scope: this
		}];


		Survey.SurveyPanel.superclass.initComponent.call(this);
	},


	onEntityChanged: function(theField, newVal/*, oldVal*/) {
		this.entityValid = false;

		if(theField.isValid()) {
			Ext.Ajax.request({
				waitTitle: MSG['wait.title'],
				waitMsg: MSG['wait.message'],
				url: CONTEXT_PATH + '/check-entity.json',
				success: function(response/*, options*/){
					var data = Ext.decode(response.responseText);

					if(data.success) {
						this.entityValid = false;
						this.entityField.markInvalid(MSG['survey.entity.duplicated']);
					} else {
						this.entityValid = true;
					}

				},
				failure: function(/*response, options*/) {
					// In case of a server error... allow survey recording
					this.entityValid = true;
				},
				params: { id: this.surveyData.id, entity: newVal},
				scope: this
			});

		}

	},

	onSave: function() {


		if(!this.getForm().isValid() && !this.entityValid) {
			return;
		}

		var formData = this.getForm().getRawValues();

		var answerRecord;
		for(var i = 0; i < this.answersStore.getCount(); ++i) {
			answerRecord = this.answersStore.getAt(i);
			formData[answerRecord.get('question_id')] = answerRecord.get('preference_id');
		}
		
		if (this.answersStore.getCount() > 0) {
			Ext.Ajax.request({
				waitTitle: MSG['wait.title'],
				waitMsg: MSG['wait.message'],
				url: CONTEXT_PATH + '/save-survey.json',
				success: function(response/*, options*/){
				
					var jsonResponse = Ext.util.JSON.decode(response.responseText);
					if( jsonResponse.success ) {
							notifySuccess(MSG['save'], MSG['save.success']);
						} else {
							notifyError( MSG['error'], jsonResponse.errors.code);
						}
					var savePanel = new Ext.Panel({
						title: jsonResponse.title,
						renderTo: 'survey-panel',
						bodyStyle: 'padding: 10px',
						iconCls: 'detecta-logo',
						html: jsonResponse.body,
						width: 760,
						height: 800
					});
				},
				failure: function(){
					notifyError(MSG['save'], MSG['save.error']);
				},
				params: formData,
				scipe: this
			});
		}else {
			notifyError(MSG['save'], MSG['survey.save.empty.error']);
		}
	},

	onCancel: function() {
		window.location = CONTEXT_PATH + "/index.jsp";
	},

	onHelp: function() {

		var helpWindow = new Ext.Window({
			title: MSG['help'],
			width: 400,
			height: 300,
			autoScroll: true,
			closable: true,
			items: [{
				xtype: 'panel',
				bodyStyle: 'padding: 10px',
				html: Ext.get('survey-help').dom.innerHTML
			}],
			buttons: [{
				text: MSG['button.ok'],
				handler: function() {
					helpWindow.close();
				},
				scope: this
			}]
		});

		helpWindow.show();

	},

	onSelectedArea: function(combo, record/*, index*/) {
		this.pathsStore.proxy.data = record.get('paths');
		this.pathsStore.load({params: {}, callback: Ext.emptyFn, add: false});
		this.pathsCombo.clearValue();

		this.questionsStore.proxy.data = [];
		this.questionsStore.load({params: {}, callback: Ext.emptyFn, add: false});
		this.questionsCombo.clearValue();
	},

	onSelectedPath: function(combo, record/*, index*/) {
		this.questionsStore.proxy.data = record.get('questions');
		this.questionsStore.load({params: {}, callback: Ext.emptyFn, add: false});
		this.questionsCombo.clearValue();
	},

	onSelectedQuestion: function(/*combo, record, index*/) {

	},

	addQuestion: function() {
		var questionIndex = this.questionsCombo.getValue();
		var pathIndex = this.pathsCombo.getValue();
		var areaIndex = this.areasCombo.getValue();
		var preferenceIndex = this.trainingPreference.getValue();

		var isValid = true;

		if(areaIndex == '') {
			this.areasCombo.markInvalid(MSG['area.empty']);
			isValid = false;
		}
		if(pathIndex == '') {
			this.pathsCombo.markInvalid(MSG['path.empty']);
			isValid = false;
		}
		if(questionIndex == '') {
			this.questionsCombo.markInvalid(MSG['path.empty']);
			isValid = false;
		}
		if(preferenceIndex == '') {
			this.trainingPreference.markInvalid(MSG['path.empty']);
			isValid = false;
		}

		if(!isValid) {
			return;
		}

		var theQuestion = this.questionsStore.find('id', questionIndex);
		if(theQuestion > -1) {
			theQuestion = this.questionsStore.getAt(theQuestion);
		}
		var thePath = this.pathsStore.find('id', pathIndex);
		if(thePath > -1) {
			thePath = this.pathsStore.getAt(thePath);
		}
		var theArea = this.areasStore.find('id', areaIndex);
		if(theArea > -1) {
			theArea = this.areasStore.getAt(theArea);
		}
		var thePreference = this.trainingPreference.store.find('id', preferenceIndex);
		if(thePreference > -1) {
			thePreference = this.trainingPreference.store.getAt(thePreference);
		}

		if(this.answersStore.find('question_id', theQuestion.get('id')) > -1) {
			notifyError(MSG['error'], MSG['question.already.added']);
			return;
		}

		var answerRecord = new this.AnswerRecord({
			id: theQuestion.get('id'),
			area_id: theArea.get('id'),
			area_description: theArea.get('description'),
			path_id: thePath.get('id'),
			path_description: thePath.get('description'),
			question_id: theQuestion.get('id'),
			question_description: theQuestion.get('description'),
			preference_id: thePreference.get('id'),
			preference_description: thePreference.get('name')
		});

		this.answersStore.add(answerRecord);
	},

	removeQuestion: function() {
		var selections = this.answersGrid.getSelectionModel().getSelections();
		for(var i = 0; i < selections.length; ++i) {
			this.answersStore.remove(selections[i]);
		}

	}
});

/**
 * Survey entry point.
 */
Survey.app = function() {

	return  {

		panel: null,

		waitDlg: null,

		init: function() {
			// Initialize quick tips
			Ext.QuickTips.init();

			var wellcomeWindow = new Ext.Window({
				title: MSG['survey.form.title'],
				width: 400,
				height: 200,
				autoScroll: true,
				closable: true,
				items: [{
					xtype: 'panel',
					bodyStyle: 'padding: 10px',
					html: Ext.get('survey-intro').dom.innerHTML
				}],
				buttons: [{
					text: MSG['button.ok'],
					handler: function() {
						wellcomeWindow.close();
					},
					scope: this
				}, {
					text: MSG['button.cancel'],
					handler: function() {
						wellcomeWindow.close();
						window.location = CONTEXT_PATH + '/index.jsp';
					},
					scope: this
				}]

			});

			wellcomeWindow.show();

			this.panel = new Survey.SurveyPanel({
				surveyData: SURVEY,
				renderTo: 'survey-panel',
				width: 760,
				// title: MSG['survey.form.title'],
				title: SURVEY.code + ' - ' + SURVEY.title,
				bodyStyle: 'padding: 10px',
				height: 800
			});

			var loading = Ext.get('loading');
			var mask = Ext.get('loading-mask');
			mask.setOpacity(0.8);
			mask.shift({
				xy: loading.getXY(),
				width: loading.getWidth(),
				height: loading.getHeight(),
				remove: true,
				duration: 2,
				opacity: 0.3,
				easing:'bounceOut',
				callback:function(){
					loading.fadeOut({
						duration: 0.2,
						remove:true
					});
				}
			});
		}


	};
}();

/**
 * Before an ajax request... show wait dialog
 */
Ext.Ajax.on("beforerequest", function() {
	this.waitDlg = Ext.Msg.wait(MSG['wait.title'], MSG['wait.text']);
}, Survey.app);

/**
 * After an ajax request... close wait dialog
 */
Ext.Ajax.on("requestcomplete", function() {
	if(this.waitDlg)  {
		this.waitDlg.hide();
	}
}, Survey.app);

/**
 * After an ajax request... close wait dialog
 */
Ext.Ajax.on("requestexception", function() {
	if(this.waitDlg)  {
		this.waitDlg.hide();
		notifyError(MSG['error'], MSG['error.message']);
	}
}, Survey.app);